package com.nuedu.corejava.jdbc1.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.nuedu.corejava.jdbc.bean.Users;
import com.nuedu.corejava.jdbc1.DBHelper;
import com.nuedu.corejava.jdbc1.dao.IUsersDao;

public class UsersDaoImpl implements IUsersDao {

	@Override
	public boolean add(Users param) {
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;

		try {

			String sql = "insert into users(id,name,age,birthday) values(SEQ_USERS.NEXTVAL,?,?,?)";
			stmt = conn.prepareStatement(sql);
			stmt.setString(1, param.getName());
			stmt.setInt(2, param.getAge());
			// 参数值是java.sql.Date,只能保存年月日；这里一般需要把util.Date转换为sql.Date
			// stmt.setDate(3, new java.sql.Date(param.getBirthDate().getTime()));
			// 参数值是java.sql.Date,只能保存时分秒；这里一般需要把util.Date转换为sql.Date
			// stmt.setTime(3, new java.sql.Date(param.getBirthDate().getTime()));

			stmt.setTimestamp(3, new java.sql.Timestamp(param.getBirthDate().getTime()));
			int count = stmt.executeUpdate();// executeUpdate会返回sql更新数据时更新了多少航，更新行数
			if (count == 1) {
				// 新增成功，返回true - 在项目中注释不能写语法，要写业务说明
				return true;// 一个方法内可以有多个return；
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public boolean edit(Users param) {

		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;

		try {
			// 根据主键修改年龄和出生日期，主键和账号不能修改
			String sql = "update users set age=?,birthday=? where id=?";// 根据主键修改年龄和出生日期
			stmt = conn.prepareStatement(sql);
			stmt.setInt(3, param.getId());
			stmt.setInt(1, param.getAge());

			stmt.setTimestamp(2, new java.sql.Timestamp(param.getBirthDate().getTime()));
			int count = stmt.executeUpdate();// executeUpdate会返回sql更新数据时更新了多少航，更新行数
			if (count == 1) {

				return true;// 一个方法内可以有多个return；
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public boolean deleteById(int id) {
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;

		try {
			// 根据主键删除数据
			String sql = "delete from  users  where id=?";
			stmt = conn.prepareStatement(sql);
			stmt.setInt(1, id);
			int count = stmt.executeUpdate();
			if (count == 1) {

				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBHelper.closeAll(null, stmt, conn);
		}
		return false;
	}

	@Override
	public Users findById(int id) {

		Users users = null;
		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;// 可以防止sql的注入攻击，在批量更新时具有良好的性能
		ResultSet rs = null;
		try {
			String sql = "select id,name,age,birthday from users where id=?";
			stmt = conn.prepareStatement(sql);
			// 4.执行sql
			// 如果sql有参数，即有？号，需要进行参数填充
			stmt.setInt(1, id);
			// 参数的序号是从1开始的，1表示第一个参数；
			rs = stmt.executeQuery();
			// 5.对sql执行结果处理
			if (rs.next()) {// next()方法从结果集中去除一行数据，如果有数据返回true，没有数据范湖false
				int id0 = rs.getInt(1);// 可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据；（有别名用别名，没有别名用列名）
				int age = rs.getInt("age");

				// getTimestamp,返回java.sql.Timestamp,Timstamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthday");

				users = new Users(id0, name, age, birthDate);

			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}

		return users;
	}

	@Override
	public List<Users> findAll() {
		List<Users> list = new ArrayList<Users>();
		// 1.注册驱动 2.建立Connection连接
		Connection conn = DBHelper.openConnection();
		// Statement statement;//可能造成sql注入攻击（在执行查询时有乔套的修改语句修改了数据）
		PreparedStatement stmt = null;// 可以防止sql的注入攻击，在批量更新时具有良好的性能
		ResultSet rs = null;
		// statement = conn.createStatement;
		try {
			// 3.打开状态连接
			String sql = "select id,name,age,birthday from users";
			stmt = conn.prepareStatement(sql);
			// 4.执行sql
			rs = stmt.executeQuery();
			// 5.对sql执行结果处理
			while (rs.next()) {// next()方法从结果集中去除一行数据，如果有数据返回true，没有数据范湖false
				int id = rs.getInt(1);// 可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据；（有别名用别名，没有别名用列名）
				int age = rs.getInt("age");

				// getTimestamp,返回java.sql.Timestamp,Timstamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthday");

				// getDate,返回java.sql.Date,sql.Date是java.util.Date的子类，可以保存： 年月日
				// birthDate = rs.getDate("birthday");
				// getDate,返回java.sql.Date,sql.Date是java.util.Date的子类，可以保存： 时分秒
				// birthDate = rs.getTime("birthday");

				Users users = new Users(id, name, age, birthDate);
				list.add(users);

			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}

		return list;
	}

	@Override
	public List<Users> findByExample(Users param) {// 根据账号进行模糊查询
		List<Users> list = new ArrayList<Users>();

		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;// 可以防止sql的注入攻击，在批量更新时具有良好的性能
		ResultSet rs = null;
		try {
			String sql = "select id,name,age,birthday from users where name like?";
			stmt = conn.prepareStatement(sql);
			// 4.执行sql
			// 如果sql有参数，即有？号，需要进行参数填充
			stmt.setString(1, "%" + param.getName() + "%");// 参数的序号是从1开始的，1表示第一个参数；
			rs = stmt.executeQuery();
			// 5.对sql执行结果处理
			while (rs.next()) {// next()方法从结果集中去除一行数据，如果有数据返回true，没有数据范湖false
				int id = rs.getInt(1);// 可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据；（有别名用别名，没有别名用列名）
				int age = rs.getInt("age");

				// getTimestamp,返回java.sql.Timestamp,Timstamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthday");

				Users users = new Users(id, name, age, birthDate);
				list.add(users);

			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}

		return list;
	}

	@Override
	public List<Users> findByPager(int page, int size) {

		List<Users> list = new ArrayList<Users>();

		Connection conn = DBHelper.openConnection();
		PreparedStatement stmt = null;// 可以防止sql的注入攻击，在批量更新时具有良好的性能
		ResultSet rs = null;
		try {
			String sql = "select * from "
					+ "(select rownum rn,id,name,age,birthday from users where rownum<=?)where rn>?";
			stmt = conn.prepareStatement(sql);
			// 4.执行sql
			// 如果sql有参数，即有？号，需要进行参数填充
			stmt.setInt(1, page * size);
			stmt.setInt(2, (page - 1) * size);// 参数的序号是从1开始的，1表示第一个参数；
			rs = stmt.executeQuery();
			// 5.对sql执行结果处理
			while (rs.next()) {// next()方法从结果集中去除一行数据，如果有数据返回true，没有数据范湖false
				int id = rs.getInt(2);// 可以根据列的序号获取列的数据，列的序号是从1开始的，1表示第一列
				String name = rs.getString("name");// 可以根据列名或列的别名获取列的数据；（有别名用别名，没有别名用列名）
				int age = rs.getInt("age");

				// getTimestamp,返回java.sql.Timestamp,Timstamp是java.util.Date的子类，可以保存： 年月日 时分秒毫秒
				Date birthDate = rs.getTimestamp("birthday");

				Users users = new Users(id, name, age, birthDate);
				list.add(users);

			}

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			// 6.关闭连接，是否资源
			DBHelper.closeAll(rs, stmt, conn);
		}

		return list;
	}

	@Override
	public int deleteByIds(int[] ids) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;

		// 业务说明：批量删除数据，只要有一条删除失败，则所有的都不删除

		try {
			connection.setAutoCommit(false);// 关闭自动提交，开启数据库事务
			String sql = "delete from users where id=?";
			stmt = connection.prepareStatement(sql);
			for (int id : ids) {
				stmt.setInt(1, id);
				stmt.addBatch();// 批量发送，没循环一次就是一批数据
			}
			int[] counts = stmt.executeBatch();// 返回一个数组，保存了每批数据更新的情况 ，每批数据更新的数量（0,1）
			for (int i : counts) {// 统计有多少批数据删除成功
				if (i == 1) {
					result++;
				}
			}
			if (result == ids.length) {
				connection.commit();// 事务提交
				connection.setAutoCommit(true);// 开启（还原）数据书屋
			} else {
				connection.rollback();// 回滚事务
			}

		} catch (SQLException e) {

			e.printStackTrace();
			if (connection != null) {
				try {
					connection.rollback();// 删除数据异常，回滚所有的事务
					connection.setAutoCommit(true);
				} catch (SQLException e1) {
					e1.printStackTrace();
				}

			}
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;
	}

	@Override
	public int addAll(List<Users> users) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;

		// 业务说明：批量添加数据，只要有一条删除失败，则所有的都不添加

		try {
			connection.setAutoCommit(false);// 关闭自动提交，开启数据库事务
			String sql = "insert into users(id,name,age,birthday) values(SEQ_USERS.NEXTVAL,?,?,?)";
			stmt = connection.prepareStatement(sql);
			for (Users user : users) {
			//	stmt = connection.prepareStatement(sql);
				stmt.setString(1, user.getName());
				stmt.setInt(2, user.getAge());
				stmt.setTimestamp(3, new java.sql.Timestamp(user.getBirthDate().getTime()));
				stmt.addBatch();// 批量发送，没循环一次就是一批数据
			}
			int[] counts = stmt.executeBatch();// 返回一个数组，保存了每批数据更新的情况 ，每批数据更新的数量（0,1）
			for (int i : counts) {// 统计有多少批数据增加成功成功
				if (i == 1) {
					result++;
				}
			}
			if (result == users.size()) {
				connection.commit();// 事务提交
				connection.setAutoCommit(true);// 开启（还原）数据事务
			} else {
				connection.rollback();// 回滚事务
			}

		} catch (SQLException e) {

			e.printStackTrace();
			if (connection != null) {
				try {
					connection.rollback();// 删除数据异常，回滚所有的事务
					connection.setAutoCommit(true);
				} catch (SQLException e1) {
					e1.printStackTrace();
				}

			}
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;
	}

	@Override
	public int editAll(List<Users> users) {
		int result = 0;
		Connection connection = DBHelper.openConnection();
		PreparedStatement stmt = null;

		// 业务说明：批量添加数据，只要有一条删除失败，则所有的都不添加

		try {
			connection.setAutoCommit(false);// 关闭自动提交，开启数据库事务
			String sql = "update users set age=?,birthday=? where id=?";
			stmt = connection.prepareStatement(sql);
			for (Users user : users) {
				stmt = connection.prepareStatement(sql);
				stmt.setInt(3, user.getId());
				stmt.setInt(1, user.getAge());
				stmt.setTimestamp(2, new java.sql.Timestamp(user.getBirthDate().getTime()));
				stmt.addBatch();// 批量发送，没循环一次就是一批数据
			}
			int[] counts = stmt.executeBatch();// 返回一个数组，保存了每批数据更新的情况 ，每批数据更新的数量（0,1）
			for (int i : counts) {// 统计有多少批数据增加成功成功
				if (i == 1) {
					result++;
				}
			}
			if (result == users.size()) {
				connection.commit();// 事务提交
				connection.setAutoCommit(true);// 开启（还原）数据事务
			} else {
				connection.rollback();// 回滚事务
			}

		} catch (SQLException e) {

			e.printStackTrace();
			if (connection != null) {
				try {
					connection.rollback();// 删除数据异常，回滚所有的事务
					connection.setAutoCommit(true);
				} catch (SQLException e1) {
					e1.printStackTrace();
				}

			}
		} finally {
			DBHelper.closeAll(null, stmt, connection);
		}

		return result;

	}
}